﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Audio;

namespace PonGun
{
    public class ParticleEmitterBase : Base2DObject
    {
        List<Particle> particlesToAdd = new List<Particle>();
        List<Particle> particles = new List<Particle>();
        List<Particle> deadParticles = new List<Particle>();

        public ParticleEmitterBase(Game1 game) : base(game) { }

        public void AddParticle(Particle particle, bool imediate = true)
        {
            if (imediate)
            {
                particle.OnParticleDied += ParticleDied;
                particles.Add(particle);
            }
            else
                particlesToAdd.Add(particle);
        }

        public virtual void ParticleDied(Base2DObject particle)
        {
            deadParticles.Add((Particle)particle);
        }

        public override void Update(GameTime gameTime)
        {
            foreach (Particle p in particlesToAdd)
                particles.Add(p);

            particlesToAdd.Clear();

            foreach (Particle p in particles)
                p.Update(gameTime);

            foreach (Particle p in deadParticles)
                particles.Remove(p);

            deadParticles.Clear();
        }

        public override void Draw(GameTime gameTime)
        {
            foreach (Particle p in particles)
            {
                if (!p.Dead)
                    p.Draw(gameTime);
            }
        }
    }

    public class Particle : Base2DObject
    {
        public ObjectCallBack OnParticleDied;

        public Vector2 PositionOffset { get; set; }

        public Base2DObject Parent { get; set; }

        public bool Dead { get; set; }
        public float Spin { get; set; }        
        public TimeSpan LifeSpan { get; set; }
        public TimeSpan Born { get; set; }
        public bool TimeToDie
        {
            get
            {
                return (LifeSpan - (DateTime.Now.TimeOfDay - Born)) < TimeSpan.Zero;
            }
        }
        public float Opacity { get; set; }
        public float FadeSpeed { get; set; }

        public int Size { get { return Width; } set { Width = value; Height = value; } }

        public Particle(Game1 game) : base(game) 
        {
            Born = DateTime.Now.TimeOfDay;
            LifeSpan = new TimeSpan(0, 0, 0, 2, 0);

            Opacity = 1;
            FadeSpeed = .01f;
            Size = 4;
        }

        public override void Update(GameTime gameTime)
        {
            Rotation += Spin;

            if (TimeToDie)
            {
                Opacity -= FadeSpeed;
                if (Opacity < 0)
                {
                    Opacity = 0;
                    KillParticle();
                }

                Color = new Color(Color.R, Color.G, Color.B, (byte)(255 * Opacity));                
            }

            if (Parent != null)
                Position = Parent.Position + PositionOffset;

            base.Update(gameTime);
        }

        public virtual void KillParticle()
        {
            Dead = true;
            if (OnParticleDied != null)
                OnParticleDied(this);
        }
    }
}
